const SFCScriptBlock = require('@vue/compiler-sfc')
const SFCDescriptor = require('@vue/compiler-sfc')
const ObjectTypeProperty = require('@vue/compiler-sfc')
const ObjectTypeSpreadProperty = require('@vue/compiler-sfc')
const Expression = require('@vue/compiler-sfc')

/**
 * 根据名称获取 scriptBlock 中的节点
 * @param {SFCScriptBlock} scriptBlock vue解析后的Script块
 * @param {string} name 名称
 * @return {ObjectTypeProperty|ObjectTypeSpreadProperty|Expression|null}
 */
function getNodeByName(scriptBlock, name) {
    if (scriptBlock.scriptAst) {
        // 声名式
        const exportDefaultNode = scriptBlock.scriptAst.find(item => item.type === 'ExportDefaultDeclaration')
        if (exportDefaultNode) {
            // 获取 props 的属性
            if (!exportDefaultNode.declaration.properties) return null
            const exportDefaultProps = exportDefaultNode.declaration.properties
            return exportDefaultProps.find(item => item.key.name === name)
        }
    } else if (scriptBlock.scriptSetupAst) {
        // setup形式
        for (let scriptSetupAstElement of scriptBlock.scriptSetupAst) {
            if (scriptSetupAstElement.type === 'VariableDeclaration') {
                // props 可能会通过变量赋值
                const value = scriptSetupAstElement.declarations[0].init
                if (value && value.callee && value.callee.name === name) {
                    return value
                }
            } else if (scriptSetupAstElement.type === 'ExpressionStatement') {
                // 没有变量的情况
                if (scriptSetupAstElement.expression.callee && scriptSetupAstElement.expression.callee.name === name) {
                    return scriptSetupAstElement.expression
                }
            }
        }
    }
    return null
}

/**
 * 获取 props 节点
 * @param {SFCScriptBlock} scriptBlock vue解析后的Script块
 * @return {ObjectTypeProperty|ObjectTypeSpreadProperty|Expression|null}
 */
function getPropsNode(scriptBlock) {
    if (scriptBlock.scriptAst) {
        return getNodeByName(scriptBlock, 'props')
    } else if (scriptBlock.scriptSetupAst) {
        return getNodeByName(scriptBlock, 'defineProps')
    }
    return null
}

/**
 * 获取 expose 节点
 * @param {SFCScriptBlock} scriptBlock vue解析后的Script块
 * @return {Expression|null}
 */
function getExposeNode(scriptBlock) {
    if (scriptBlock.scriptAst) return null
    return getNodeByName(scriptBlock, 'defineExpose')
}

/**
 * 获取 emits 节点
 * @param {SFCScriptBlock} scriptBlock vue解析后的Script块
 * @return {Expression|null}
 */
function getEmitsNode(scriptBlock) {
    if (scriptBlock.scriptSetupAst) {
        return getNodeByName(scriptBlock, 'defineEmits')
    }
    return null
}

/**
 * 获取节点值
 * @param node
 * @return {*|string}
 */
function getNodeValue(node) {
    if (!node) return ''
    if (node.type === 'NullLiteral') return ''
    if (node.type === 'Identifier') {
        return node.name
    } else if (node.type.endsWith('Literal')) {
        return node.value
    }
    return ''
}

exports.getPropsNode = getPropsNode
exports.getExposeNode = getExposeNode
exports.getEmitsNode = getEmitsNode
exports.getNodeValue = getNodeValue
